// Copyright 2021 Guoyoko. All Rights Reserved.

#include "Slate/SSWPropertyVectorWidget.h"
#include "Widgets/Input/SCheckBox.h"
//#include "Widgets/Input/SVectorInputBox.h"
#include "Widgets/Input/SNumericEntryBox.h"


void SSWPropertyVectorWidget::Construct(const FArguments& InArgs, FSWBaseProperty* InBaseProperty)
{
	SSWPropertyRowBaseWidget::Construct(SSWPropertyRowBaseWidget::FArguments().NodeName(InArgs._NodeName), InBaseProperty); 

	TSharedRef<SBox> PropertyLeftRow =
		SNew(SBox)
		[
			SNew(STextBlock)
			.Text(FText::FromName(NodeName))
		];

	TSharedRef<SHorizontalBox> PropertyRightRow = SNew(SHorizontalBox);

	ConstructX(InArgs, PropertyRightRow);
	ConstructY(InArgs, PropertyRightRow);
	ConstructZ(InArgs, PropertyRightRow);

	ChildSlot
	[
		SNew(SHorizontalBox)
		+ SHorizontalBox::Slot()
		[
			PropertyLeftRow
		]
		+ SHorizontalBox::Slot()
		[
			PropertyRightRow
		]
	];
}

void SSWPropertyVectorWidget::ConstructX(const FArguments& InArgs, TSharedRef<SHorizontalBox> HorizontalBox)
{
	const FLinearColor LabelColor = FLinearColor(0.594f, 0.0197f, 0.0f);
	TSharedRef<SWidget> LabelWidget = SNumericEntryBox<float>::BuildLabel(INVTEXT("X"), FLinearColor::White, LabelColor);
	
	HorizontalBox->AddSlot()
		.VAlign(VAlign_Center)
		.FillWidth(1.0f)
		.Padding(0.0f, 1.0f, 2.0f, 1.0f)
		[
			SNew(SNumericEntryBox<float>)
			.AllowSpin(true)
			.Value(this, &SSWPropertyVectorWidget::GetLocationX)
			.OnValueChanged(this, &SSWPropertyVectorWidget::OnSetTransformAxis, ETextCommit::Default, EAxisList::X, false)
			.OnValueCommitted(this, &SSWPropertyVectorWidget::OnSetTransformAxis, EAxisList::X, true)
			.UndeterminedString(INVTEXT("Multiple Values"))
			.LabelPadding(0)
			.MinValue(TOptional<float>())
			.MaxValue(TOptional<float>())
			.MinSliderValue(TOptional<float>())
			.MaxSliderValue(TOptional<float>())
			.LinearDeltaSensitivity(1)
			.Label()
			[
				LabelWidget
			]
		];
}

void SSWPropertyVectorWidget::ConstructY(const FArguments& InArgs, TSharedRef<SHorizontalBox> HorizontalBox)
{
	const FLinearColor LabelColor = FLinearColor(0.1349f, 0.3959f, 0.0f);
		TSharedRef<SWidget> LabelWidget = SNumericEntryBox<float>::BuildLabel(INVTEXT("Y"), FLinearColor::White, LabelColor);

	HorizontalBox->AddSlot()
		.VAlign(VAlign_Center)
		.FillWidth(1.0f)
		.Padding(0.0f, 1.0f, 2.0f, 1.0f)
		[
			SNew(SNumericEntryBox<float>)
			.AllowSpin(true)
			.Value(this, &SSWPropertyVectorWidget::GetLocationY)
			.OnValueChanged(this, &SSWPropertyVectorWidget::OnSetTransformAxis, ETextCommit::Default, EAxisList::Y, false)
			.OnValueCommitted(this, &SSWPropertyVectorWidget::OnSetTransformAxis, EAxisList::Y, true)
			.UndeterminedString(INVTEXT("Multiple Values"))
			.LabelPadding(0)
			.MinValue(TOptional<float>())
			.MaxValue(TOptional<float>())
			.MinSliderValue(TOptional<float>())
			.MaxSliderValue(TOptional<float>())
			.LinearDeltaSensitivity(1)
			.Label()
			[
				LabelWidget
			]
		];
}

void SSWPropertyVectorWidget::ConstructZ(const FArguments& InArgs, TSharedRef<SHorizontalBox> HorizontalBox)
{
	const FLinearColor LabelColor = FLinearColor(0.0251f, 0.207f, 0.85f);
		TSharedRef<SWidget> LabelWidget = SNumericEntryBox<float>::BuildLabel(INVTEXT("Z"), FLinearColor::White, LabelColor);

	HorizontalBox->AddSlot()
		.VAlign(VAlign_Center)
		.FillWidth(1.0f)
		.Padding(0.0f, 1.0f, 2.0f, 1.0f)
		[
			SNew(SNumericEntryBox<float>)
			.AllowSpin(true)
			.Value(this, &SSWPropertyVectorWidget::GetLocationZ)
			.OnValueChanged(this, &SSWPropertyVectorWidget::OnSetTransformAxis, ETextCommit::Default, EAxisList::Z, false)
			.OnValueCommitted(this, &SSWPropertyVectorWidget::OnSetTransformAxis, EAxisList::Z, true)
			.UndeterminedString(INVTEXT("Multiple Values"))
			.LabelPadding(0)
			.MinValue(TOptional<float>())
			.MaxValue(TOptional<float>())
			.MinSliderValue(TOptional<float>())
			.MaxSliderValue(TOptional<float>())
			.LinearDeltaSensitivity(1)
			.Label()
			[
				LabelWidget
			]
		];
}

TOptional<float> SSWPropertyVectorWidget::GetLocationX() const
{
	if (BaseProperty->SelectedActor != nullptr)
	{
		return BaseProperty->SelectedActor->GetActorLocation().X;
	}
	return 0.f;
}

TOptional<float> SSWPropertyVectorWidget::GetLocationY() const
{
	if (BaseProperty->SelectedActor != nullptr)
	{
		return BaseProperty->SelectedActor->GetActorLocation().Y;
	}
	return 0.f;
}

TOptional<float> SSWPropertyVectorWidget::GetLocationZ() const
{
	if (BaseProperty->SelectedActor != nullptr)
	{
		return BaseProperty->SelectedActor->GetActorLocation().Z;
	}
	return 0.f;
}

void SSWPropertyVectorWidget::OnSetTransformAxis(float NewValue, ETextCommit::Type CommitInfo, EAxisList::Type Axis, bool bCommitted)
{
	if (BaseProperty->SelectedActor != nullptr)
	{
		FVector NewVector;
		if (Axis == EAxisList::Type::X)
		{
			NewVector = FVector(NewValue, GetLocationY().GetValue(), GetLocationZ().GetValue());
		}
		else if (Axis == EAxisList::Type::Y)
		{
			NewVector = FVector(GetLocationX().GetValue(), NewValue, GetLocationZ().GetValue());
		}
		else if (Axis == EAxisList::Type::Z)
		{
			NewVector = FVector(GetLocationX().GetValue(), GetLocationY().GetValue(), NewValue);
		}
		BaseProperty->SelectedActor->SetActorLocation(NewVector);
	}
}

